package cn.analysys.test;

import cn.analysys.model.Person;
import org.activiti.engine.*;
import org.activiti.engine.identity.User;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Attachment;
import org.activiti.engine.task.Task;

import java.io.*;
import java.util.List;
import java.util.UUID;

/**
 * 一、任务权限
 *      任务候选人(组) ： 一个任务可以有多个候选人
 *      任务持有人：一个任务只有一个持有人
 *      任务代理人：一个任务只有一个代理人
 *
 * 二、任务的声明与完成
 *
 * 三、任务参数 （任务参数表：act_ru_variable）
 *      基本数据参数类型
 *      序列化参数
 *
 * 四、参数作用域
 *      本地参数 ： 本地参数只存在于当前任务
 *      全局参数
 *
 *  五、数据对象
 *  六、任务附件 (资源表：act_ge_bytearray  附件表：act_hi_attachment)
 *
 *
 */
public class TaskTest3 {

    public static void main(String[] args) throws IOException {
        // 设置任务到候选人
//        addCandidateUser();

        // 设置任务持有人
//        setOwner();

        // 设置任务代理人
//        setAssignee();

        // 声明代理人
//        claim();

        // 任务完成
//        complete();

        // 设置任务参数
//        setVariable();

        // 设置本地参数
//        setVariable2();

        // 设置全局参数
//        setVariable3();

        // 获取dataObject参数
//        getDataObject();

        // 任务附件
        attachment();
    }

    /**
     * 设置任务到候选人
     */
    public static void addCandidateUser() {
        // 创建流程引擎
        ProcessEngine engine = ProcessEngines.getDefaultProcessEngine();
        // 创建任务服务
        TaskService taskService = engine.getTaskService();
        // 创建用户服务
        IdentityService identityService = engine.getIdentityService();

        // 创建一个任务 (act_ru_task)
        String taskId = UUID.randomUUID().toString();
        Task task = taskService.newTask(taskId);
        task.setName("测试任务");
        taskService.saveTask(task);

        //创建一个用户 (act_id_user)
        String userId = UUID.randomUUID().toString();
        User user = identityService.newUser(userId);
        user.setFirstName("测试用户");
        identityService.saveUser(user);
        // 设置任务到候选人(表：act_ru_identitylink)
        taskService.addCandidateUser(taskId, userId);

        //创建一个用户组 (act_id_group)
//        String groupId = UUID.randomUUID().toString();
//        Group group = identityService.newGroup(groupId);
//        group.setName("测试用户组");
//        identityService.saveGroup(group);
//        // 设置任务到候选用户组
//        taskService.addCandidateGroup(taskId,groupId);

        // 查询用户有权限处理的任务 (act_ru_identitylink)
        List<Task> taskList = taskService.createTaskQuery().taskCandidateUser(userId).list();
        for (Task task1 : taskList) {
            System.out.println(task1.getName());
        }

    }

    /**
     * 设置任务持有人
     */
    public static void setOwner() {
        // 创建流程引擎
        ProcessEngine engine = ProcessEngines.getDefaultProcessEngine();
        // 创建任务服务
        TaskService taskService = engine.getTaskService();
        // 创建用户服务
        IdentityService identityService = engine.getIdentityService();

        // 创建一个任务 (act_ru_task)
        String taskId = UUID.randomUUID().toString();
        Task task = taskService.newTask(taskId);
        task.setName("测试任务(持有人)");
        taskService.saveTask(task);

        //创建一个用户 (act_id_user)
        String userId = UUID.randomUUID().toString();
        User user = identityService.newUser(userId);
        user.setFirstName("测试用户(持有人)");
        identityService.saveUser(user);

        // 设置任务持有人(修改表：act_ru_task的OWNER_字段)
        taskService.setOwner(taskId, userId);


        // 查询用户持有的任务 (act_ru_task)
        List<Task> taskList = taskService.createTaskQuery().taskOwner(userId).list();
        for (Task task1 : taskList) {
            System.out.println(task1.getName());
        }
    }


    /**
     * 设置任务代理人
     */
    public static void setAssignee() {
        // 创建流程引擎
        ProcessEngine engine = ProcessEngines.getDefaultProcessEngine();
        // 创建任务服务
        TaskService taskService = engine.getTaskService();
        // 创建用户服务
        IdentityService identityService = engine.getIdentityService();

        // 创建一个任务 (act_ru_task)
        String taskId = UUID.randomUUID().toString();
        Task task = taskService.newTask(taskId);
        task.setName("测试任务(代理人)");
        taskService.saveTask(task);

        //创建一个用户 (act_id_user)
        String userId = UUID.randomUUID().toString();
        User user = identityService.newUser(userId);
        user.setFirstName("测试用户(代理人)");
        identityService.saveUser(user);

        // 设置任务代理人(修改表：act_ru_task的ASSIGNEE_字段)
        taskService.setAssignee(taskId, userId);

        // 查询用户代理的任务 (act_ru_task)
        List<Task> taskList = taskService.createTaskQuery().taskAssignee(userId).list();
        for (Task task1 : taskList) {
            System.out.println(task1.getName());
        }
    }


    /**
     * 声明任务代理人
     */
    public static void claim() {
        // 创建流程引擎
        ProcessEngine engine = ProcessEngines.getDefaultProcessEngine();
        // 创建任务服务
        TaskService taskService = engine.getTaskService();
        // 创建用户服务
        IdentityService identityService = engine.getIdentityService();

        // 创建一个任务 (act_ru_task)
        String taskId = UUID.randomUUID().toString();
        Task task = taskService.newTask(taskId);
        task.setName("测试任务(声明任务)");
        taskService.saveTask(task);

        //创建一个用户 (act_id_user)
        String userId = UUID.randomUUID().toString();
        User user = identityService.newUser(userId);
        user.setFirstName("测试用户(声明任务)");
        identityService.saveUser(user);

        // 声明任务代理人
        // 和taskService.setAssignee()的区别时，重复声明会报错。
        taskService.claim(taskId, userId);

        // 查询用户代理的任务 (act_ru_task)
        List<Task> taskList = taskService.createTaskQuery().taskAssignee(userId).list();
        for (Task task1 : taskList) {
            System.out.println(task1.getName());
        }
    }

    /**
     * 完成任务
     */
    public static void complete() {
        // 创建流程引擎
        ProcessEngine engine = ProcessEngines.getDefaultProcessEngine();
        // 创建任务服务
        TaskService taskService = engine.getTaskService();

        // 创建一个任务 (act_ru_task)
        String taskId = UUID.randomUUID().toString();
        Task task = taskService.newTask(taskId);
        task.setName("测试任务(完成任务)");
        taskService.saveTask(task);

        // 完成任务
        taskService.complete(taskId);

    }

    /**
     * 设置任务参数
     */
    public static void setVariable() {
        // 创建流程引擎
        ProcessEngine engine = ProcessEngines.getDefaultProcessEngine();
        // 创建任务服务
        TaskService taskService = engine.getTaskService();

        // 创建一个任务 (act_ru_task)
        String taskId = UUID.randomUUID().toString();
        Task task = taskService.newTask(taskId);
        task.setName("测试任务");
        taskService.saveTask(task);

        // 保存基本数据类型 (act_ru_variable)
        taskService.setVariable(task.getId(),"var1","hello");

        // 保存对象
        // 1.保存到 act_ru_variable
        // 2.将对象序列化，然后保存到act_ge_bytearray
        Person person = new Person();
        person.setId(1);
        person.setName("person");
        taskService.setVariable(task.getId(), "person1", person);

        Person person1 = taskService.getVariable(task.getId(),"person1",Person.class);
        System.out.println(person1.toString());

    }


    /**
     * 设置本地参数
     */
    public static void setVariable2() {
        // 创建流程引擎
        ProcessEngine engine = ProcessEngines.getDefaultProcessEngine();
        // 存储服务
        RepositoryService repositoryService=  engine.getRepositoryService();
        // 创建任务服务
        TaskService taskService = engine.getTaskService();
        // 运行时服务
        RuntimeService runtimeService = engine.getRuntimeService();
        // 部署流程定义
        Deployment deployment = repositoryService.createDeployment().addClasspathResource("datas/var_local.bpmn").deploy();
        // 查询流程定义实体 (查询：act_re_procdef)
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
                .deploymentId(deployment.getId()).singleResult();
        // 得到流程实例
        ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(processDefinition.getKey());

        // 得到该流程任务
        Task task = taskService.createTaskQuery().processInstanceId(processInstance.getId()).singleResult();
        // 设置任务本地参数，本地参数只存在于当前任务
        taskService.setVariableLocal(task.getId(),"day",3);

        System.out.println("验前任务：" + task.getId() + "，day参数：" + taskService.getVariableLocal(task.getId(),"day"));

        // 完成任务
        taskService.complete(task.getId());

        // 得到该流程任务
        task = taskService.createTaskQuery().processInstanceId(processInstance.getId()).singleResult();
        System.out.println("验后任务：" + task.getId() + "，day参数：" + taskService.getVariableLocal(task.getId(),"day"));

    }

    /**
     * 设置全局参数
     */
    public static void setVariable3() {
        // 创建流程引擎
        ProcessEngine engine = ProcessEngines.getDefaultProcessEngine();
        // 存储服务
        RepositoryService repositoryService=  engine.getRepositoryService();
        // 创建任务服务
        TaskService taskService = engine.getTaskService();
        // 运行时服务
        RuntimeService runtimeService = engine.getRuntimeService();
        // 部署流程定义
        Deployment deployment = repositoryService.createDeployment().addClasspathResource("datas/var_local.bpmn").deploy();
        // 查询流程定义实体 (查询：act_re_procdef)
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
                .deploymentId(deployment.getId()).singleResult();
        // 得到流程实例
        ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(processDefinition.getKey());

        // 得到该流程任务
        Task task = taskService.createTaskQuery().processInstanceId(processInstance.getId()).singleResult();
        // 设置任务全局参数，全局参数存在于所有任务
        taskService.setVariable(task.getId(),"day",3);

        System.out.println("验前任务：" + task.getId() + "，day参数：" + taskService.getVariable(task.getId(),"day"));

        // 完成任务
        taskService.complete(task.getId());

        // 得到该流程任务
        task = taskService.createTaskQuery().processInstanceId(processInstance.getId()).singleResult();
        System.out.println("验后任务：" + task.getId() + "，day参数：" + taskService.getVariable(task.getId(),"day"));
    }


    /**
     * 获取dataObject参数
     */
    public static void getDataObject() {
        // 创建流程引擎
        ProcessEngine engine = ProcessEngines.getDefaultProcessEngine();
        // 存储服务
        RepositoryService repositoryService=  engine.getRepositoryService();
        // 创建任务服务
        TaskService taskService = engine.getTaskService();
        // 运行时服务
        RuntimeService runtimeService = engine.getRuntimeService();
        // 部署流程定义
        Deployment deployment = repositoryService.createDeployment().addClasspathResource("datas/dataObject.bpmn").deploy();
        // 查询流程定义实体 (查询：act_re_procdef)
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
                .deploymentId(deployment.getId()).singleResult();
        // 得到流程实例
        ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(processDefinition.getKey());

        // 得到该流程任务
        Task task = taskService.createTaskQuery().processInstanceId(processInstance.getId()).singleResult();
        System.out.println(taskService.getVariable(task.getId(),"personName"));
       }


    /**
     * 任务附件
     */
    public static void attachment() throws FileNotFoundException {
        // 创建流程引擎
        ProcessEngine engine = ProcessEngines.getDefaultProcessEngine();
        // 存储服务
        RepositoryService repositoryService=  engine.getRepositoryService();
        // 创建任务服务
        TaskService taskService = engine.getTaskService();
        // 运行时服务
        RuntimeService runtimeService = engine.getRuntimeService();
        // 部署流程定义
        Deployment deployment = repositoryService.createDeployment().addClasspathResource("datas/var_local.bpmn").deploy();
        // 查询流程定义实体 (查询：act_re_procdef)
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
                .deploymentId(deployment.getId()).singleResult();
        // 得到流程实例
        ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(processDefinition.getKey());
        // 得到该流程任务
        Task task = taskService.createTaskQuery().processInstanceId(processInstance.getId()).singleResult();

        // 第一种方式：设置任务附件
        Attachment attachment1 =  taskService.createAttachment("web url",task.getId(),processInstance.getId(),
                "163.com","163 web page", "http://www.163.com");


        //第二种方式：设置任务附件
        InputStream inputStream = new FileInputStream(new File(RepositoryTest2.class.getResource("/").getPath() + "/datas/demo.png"));
        //设置输入流为任务附件
        Attachment attachment2 = taskService.createAttachment("web url",task.getId(),processInstance.getId()
                ,"163.com","163 web page", inputStream);


        // 1.根据流程实例ID查询该流程实例下全部附件
        List<Attachment> attachments = taskService.getProcessInstanceAttachments(processInstance.getId());

        // 2.根据任务ID查询该任务下全部附件
        attachments =  taskService.getTaskAttachments(task.getId());

        // 3. 根据附件ID查询附件数据
        Attachment attachment = taskService.getAttachment(attachment1.getId());

        // 4. 根据附件ID查询附件数据,获取附件的输入流对象
        InputStream inputStream1 =  taskService.getAttachmentContent(attachment2.getId());

        System.out.println();
    }


}
